home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / mpeg / fs4.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  8KB  |  306 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  * 
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  * 
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. /* This file contains C code to do YCrCb -> colormap space. */
  22.  
  23. #include "fs4.h"
  24. #include "video.h"
  25. #include "proto.h"
  26. #include "dither.h"
  27.  
  28. /* Structures containing precomputed error terms. */
  29.  
  30. static FS4Dither lum_index[256];
  31. static FS4Dither cr_index[256];
  32. static FS4Dither cb_index[256];
  33.  
  34.  
  35. /*
  36.  *--------------------------------------------------------------
  37.  *
  38.  * InitFS4Dither --
  39.  *
  40.  *    Initializes structures used for f-s dithering. Precomputes
  41.  *      error terms.
  42.  *
  43.  * Results:
  44.  *    None.
  45.  *
  46.  * Side effects:
  47.  *      None.
  48.  *
  49.  *--------------------------------------------------------------
  50.  */
  51.  
  52. void
  53. InitFS4Dither()
  54. {
  55.   int i;
  56.  
  57.   for (i=0; i<256; i++) {
  58.     lum_index[i].value = (i * LUM_RANGE) / 256;
  59.  
  60.     lum_index[i].e1 = (7 * (i-lum_values[lum_index[i].value])) / 16;
  61.     lum_index[i].e2 = (i-lum_values[lum_index[i].value])/16;
  62.     lum_index[i].e3 = (5 *  (i - lum_values[lum_index[i].value])) / 16;
  63.     lum_index[i].e4 = (i-lum_values[lum_index[i].value]) - lum_index[i].e1 -
  64.       lum_index[i].e2 - lum_index[i].e3;
  65.  
  66.     lum_index[i].value *= LUM_BASE;
  67.  
  68.     cr_index[i].value = (i * CR_RANGE) / 256; 
  69.  
  70.     cr_index[i].e1 = (7 * (i-cr_values[cr_index[i].value])) / 16;
  71.     cr_index[i].e2 = (i-cr_values[cr_index[i].value])/16;
  72.     cr_index[i].e3 = (5 *  (i - cr_values[cr_index[i].value])) / 16;
  73.     cr_index[i].e4 = (i-cr_values[cr_index[i].value]) - cr_index[i].e1 -
  74.       cr_index[i].e2 - cr_index[i].e3;
  75.     cr_index[i].value *= CR_BASE;
  76.  
  77.     cb_index[i].value = (i * CB_RANGE) / 256; 
  78.  
  79.     cb_index[i].e1 = (7 * (i-cb_values[cb_index[i].value])) / 16;
  80.     cb_index[i].e2 = (i-cb_values[cb_index[i].value])/16;
  81.     cb_index[i].e3 = (5 *  (i - cb_values[cb_index[i].value])) / 16;
  82.     cb_index[i].e4 = (i-cb_values[cb_index[i].value]) - cb_index[i].e1 -
  83.       cb_index[i].e2 - cb_index[i].e3;
  84.     cb_index[i].value *= CB_BASE;
  85.  
  86.   }
  87.  
  88. }
  89.  
  90.  
  91. /*
  92.  *--------------------------------------------------------------
  93.  *
  94.  * DitherImage --
  95.  *
  96.  *    Converts lum, cr, cb image planes into fixed colormap
  97.  *      space. Uses Floyd-Steinberg dithering in serpentine
  98.  *      pattern with standard 4 errors propogated.
  99.  *
  100.  * Results:
  101.  *    The display plane is replaced by 8-bit colormap space
  102.  *      image.
  103.  *
  104.  * Side effects:
  105.  *      Hopefully, none.
  106.  *
  107.  *--------------------------------------------------------------
  108.  */
  109.  
  110. void 
  111. FS4DitherImage(lum, cr, cb, disp, rows, cols)
  112.      unsigned char *lum, *cr, *cb, *disp;
  113.      int rows, cols;
  114. {
  115.   static char *cur_row_error, *next_row_error;
  116.   static int first = 1;
  117.   char  *cur_row_err_mark, *next_row_err_mark;
  118.   char *temp;
  119.   int i, j, pixsum, c_cols;
  120.   unsigned char *cur_row, *channel, *dest_row;
  121.   FS4Dither *chan_index;
  122.  
  123.   if (first) {
  124.     cur_row_error = (char *) malloc(cols+2);
  125.     next_row_error = (char *) malloc(cols+2);
  126.     first = 0;
  127.   }
  128.  
  129.   memset(cur_row_error, 0, cols+2);
  130.   memset(next_row_error, 0, cols+2);
  131.  
  132.   for(i=0; i<rows; i+=2) {
  133.      cur_row = lum + (i*cols);
  134.      dest_row = disp + (i*cols);
  135.  
  136.      cur_row_err_mark = cur_row_error + 1;
  137.      next_row_err_mark = next_row_error + 1;
  138.  
  139.      for (j=0; j<cols; j++) {
  140.  
  141.        pixsum = *cur_row + *cur_row_err_mark;
  142.        if (pixsum < 0) pixsum = 0;
  143.        else if (pixsum > 255) pixsum = 255;
  144.  
  145.        *dest_row = lum_index[pixsum].value;
  146.        *(cur_row_err_mark+1) += lum_index[pixsum].e1; 
  147.        *(next_row_err_mark+1) += lum_index[pixsum].e2;
  148.        *next_row_err_mark += lum_index[pixsum].e3; 
  149.        *(next_row_err_mark-1) += lum_index[pixsum].e4;
  150.  
  151.        cur_row++;
  152.        dest_row++;
  153.        cur_row_err_mark++;
  154.        next_row_err_mark++;
  155.      }
  156.  
  157.      temp = cur_row_error;
  158.      cur_row_error = next_row_error;
  159.      next_row_error = temp;
  160.  
  161.      memset(next_row_error, 0, cols+2); 
  162.  
  163.      cur_row += cols-1;
  164.      dest_row += cols-1;
  165.      cur_row_err_mark = cur_row_error + cols;
  166.      next_row_err_mark = next_row_error + cols;
  167.  
  168.      for (j=0; j<cols; j++) {
  169.  
  170.        pixsum = *cur_row + *cur_row_err_mark;
  171.        if (pixsum < 0) pixsum = 0;
  172.        else if (pixsum > 255) pixsum = 255;
  173.  
  174.        *dest_row = lum_index[pixsum].value;
  175.        *(cur_row_err_mark-1) += lum_index[pixsum].e1; 
  176.        *(next_row_err_mark-1) += lum_index[pixsum].e2;
  177.        *next_row_err_mark += lum_index[pixsum].e3; 
  178.        *(next_row_err_mark+1) += lum_index[pixsum].e4;
  179.  
  180.        cur_row--;
  181.        dest_row--;
  182.        cur_row_err_mark--;
  183.        next_row_err_mark--;
  184.      }
  185.  
  186.      temp = cur_row_error;
  187.      cur_row_error = next_row_error;
  188.      next_row_error = temp;
  189.  
  190.      memset(next_row_error, 0, cols+2); 
  191.    }
  192.  
  193.   memset(cur_row_error, 0, cols+2); 
  194.  
  195.   c_cols = cols >> 1;
  196.  
  197.   channel = cr;
  198.   chan_index = cr_index;
  199.  
  200.  repeat:
  201.  
  202.   for (i=0; i < rows; i+=2) {
  203.     cur_row = channel + ((i>>1)*c_cols);
  204.     dest_row = disp + (i*cols);
  205.  
  206.     cur_row_err_mark = cur_row_error+1;
  207.     next_row_err_mark = next_row_error+1;
  208.     
  209.     for (j=0; j<cols; j++) {
  210.       int p_val;
  211.  
  212.       p_val = *cur_row;
  213.  
  214.       pixsum = *cur_row_err_mark + p_val;
  215.  
  216.       if (pixsum < 0) pixsum = 0;
  217.       else if (pixsum > 255) pixsum = 255;
  218.  
  219.       *dest_row += chan_index[pixsum].value;
  220.  
  221.       *(cur_row_err_mark+1) += chan_index[pixsum].e1; 
  222.       *(next_row_err_mark+1) += chan_index[pixsum].e2;
  223.       *next_row_err_mark += chan_index[pixsum].e3; 
  224.       *(next_row_err_mark-1) += chan_index[pixsum].e4;
  225.  
  226.  
  227.       if (j&1) cur_row++;
  228.       dest_row++;
  229.       cur_row_err_mark++;
  230.       next_row_err_mark++;
  231.     }
  232.       
  233.     temp = cur_row_error;
  234.     cur_row_error = next_row_error;
  235.     next_row_error = temp;
  236.  
  237.     memset(next_row_error, 0, cols+2);
  238.  
  239.     cur_row += c_cols-1;
  240.     dest_row += cols-1;
  241.     cur_row_err_mark = cur_row_error+cols;
  242.     next_row_err_mark = next_row_error+cols;
  243.  
  244.     for (j=0; j<cols; j++) {
  245.       int p_val;
  246.  
  247.       p_val = *cur_row;
  248.  
  249.       pixsum = *cur_row_err_mark + p_val;
  250.  
  251.       if (pixsum < 0) pixsum = 0;
  252.       else if (pixsum > 255) pixsum = 255;
  253.  
  254.       *dest_row += chan_index[pixsum].value;
  255.  
  256.       *(cur_row_err_mark-1) += chan_index[pixsum].e1; 
  257.       *(next_row_err_mark-1) += chan_index[pixsum].e2;
  258.       *next_row_err_mark += chan_index[pixsum].e3; 
  259.       *(next_row_err_mark+1) += chan_index[pixsum].e4;
  260.  
  261.       if (j&1) cur_row--;
  262.       dest_row--;
  263.       cur_row_err_mark--;
  264.       next_row_err_mark--;
  265.     }
  266.  
  267.     temp = cur_row_error;
  268.     cur_row_error = next_row_error;
  269.     next_row_error = temp;
  270.  
  271.     memset(next_row_error, 0, cols+2);
  272.   }
  273.  
  274.   if (channel == cr) {
  275.     channel = cb;
  276.     chan_index = cb_index;
  277.     memset(cur_row_error, 0, cols+2);
  278.  
  279.     goto repeat;
  280.   }
  281.  
  282.   dest_row = disp;
  283.  
  284.  
  285.   for (i=0; i<rows; i++) {
  286.     for (j=0; j<cols; j++) {
  287.       *dest_row =  pixel[*dest_row];
  288.       dest_row++;
  289.     }
  290.   }
  291. }
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.